package com.black.play.component.base;

import com.black.play.common.ExitAble;
import com.black.play.common.FormComponent;
import com.black.play.common.FormItem;
import com.black.play.component.box.AppInputBox;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.List;

public class AppForm extends JPanel implements ExitAble {
    private final Map<String, FormComponent<?>> formMap = new LinkedHashMap<>();
    private final JPanel formPanel = new JPanel(new GridBagLayout());
    private final JScrollPane scrollPane = new JScrollPane(formPanel);
    private final AppButton submitButton;
    private final AppButton cancelButton;
    private final GridBagConstraints constraints = new GridBagConstraints();

    public static AppForm buildForm(List<FormItem> formItems) {
        return buildForm(formItems, "Submit", "Cancel");
    }

    public static AppForm buildForm(List<FormItem> formItems, String submitLabel, String cancelLabel) {
        AppForm appForm = new AppForm(submitLabel, cancelLabel);
        formItems.forEach(formItem -> {
            switch (formItem.getType()) {
                case INPUT:
                    appForm.addInput(formItem.getLabel(), formItem.getValue());
                    break;
                case MULTILINE_INPUT:
                    appForm.addMultilineInput(formItem.getLabel(), formItem.getValue(), 3);
                    break;
                case RADIO_BUTTON_GROUP:
                    appForm.addRadioButtonGroup(formItem.getLabel(), formItem.getOptions(), formItem.getValue());
                    break;
            }
        });
        return appForm;
    }

    public AppForm() {
        this("Submit", "Cancel");
    }

    public AppForm(String submitLabel, String cancelLabel) {
        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        constraints.insets = new Insets(5, 5, 5, 5);
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weightx = 1.0;

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));

        submitButton = new AppButton(submitLabel);
        cancelButton = new AppButton(cancelLabel);

        buttonPanel.add(submitButton);
        buttonPanel.add(cancelButton);

        add(buttonPanel, BorderLayout.SOUTH);
    }

    @Override
    public void setBackground(Color color) {
        super.setBackground(color);
        if (scrollPane != null) {
            scrollPane.setBackground(color);
        }
        if (formPanel != null) {
            formPanel.setBackground(color);
        }
    }

    public void addInput(String label) {
        addInput(label, "");
    }

    public void addInput(String label, String value) {
        AppInput appInput = new AppInput(label, value, 20);
        addComponent(label, appInput);
    }

    public void addMultilineInput(String label) {
        addMultilineInput(label, 3);
    }

    public void addMultilineInput(String label, int row) {
        addMultilineInput(label, "", row);
    }

    public void addMultilineInput(String label, String value, int row) {
        AppInputBox appInputBox = new AppInputBox(label, value, row, 20);
        addComponent(label, appInputBox);
    }

    public void addRadioButtonGroup(String label, String[] options) {
        addRadioButtonGroup(label, options, options[0]);
    }

    public void addRadioButtonGroup(String label, String[] options, String value) {
        AppRadio appRadio = new AppRadio(label, options, value);
        addComponent(label, appRadio);
    }

    public void addComponent(String label, FormComponent<?> component) {
        this.constraints.gridy = this.formMap.size();
        this.formPanel.add(component, this.constraints);
        this.formMap.put(label, component);
        resize();
        updateUI();
    }

    public void addKeyListener(String label, KeyAdapter actionListener) {
        FormComponent<?> item = formMap.get(label);
        item.addKeyListener(actionListener);
    }

    public void remove(String label) {
        FormComponent<?> remove = formMap.remove(label);
        formPanel.remove(remove);
        revalidate();
        repaint();
    }

    public String get(String label) {
        FormComponent<?> item = formMap.get(label);
        return item.getValue();
    }

    public void set(String label, String value) {
        FormComponent<?> item = formMap.get(label);
        item.setValue(value);
        updateUI();
    }

    public void addSubmitAction(ActionListener actionListener) {
        submitButton.addActionListener(actionListener);
    }

    public void addCancelAction(ActionListener actionListener) {
        cancelButton.addActionListener(actionListener);
    }

    private void resize() {
        Collection<FormComponent<?>> values = formMap.values();
        int maxLength = values.stream().map(FormComponent::getLabel).map(String::length).max(Integer::compareTo).get();
        // 根据最长label对齐
        for (FormComponent<?> item : values) {
            Dimension size = item.getLabelSize();
            item.setLabelSize(new Dimension(maxLength + 5, size.height));
        }
        // 根据输入框对齐
        values.stream().filter(item -> item instanceof AppInput).findAny().ifPresent(item -> {
            Dimension componentSize = item.getComponentSize();
            for (FormComponent<?> value : values) {
                Dimension preSize = value.getComponentSize();
                value.setComponentSize(new Dimension(componentSize.width, preSize.height));
            }
        });
    }

    @Override
    public void exit(ActionEvent... actionEvents) {
        Container parent = getParent();
        while (parent != null && !(parent instanceof JFrame)) {
            parent = parent.getParent();
        }
        if (parent instanceof ExitAble) {
            ((ExitAble) parent).exit(actionEvents);
        }
    }
}
